home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- *
- * NSSDC/CDF Directory utilities.
- *
- * Version 1.0, 3-Mar-92, ST Systems (STX)
- *
- * Modification history:
- *
- * V1.0 3-Mar-92, J Love Original version.
- *
- *****************************************************************************/
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
-
- #if defined(__MSDOS__) /* Borland/Turbo C */
- #include <dir.h>
- #include <dos.h>
- #include <sys\stat.h>
- #endif
-
- #if defined(MSDOS) /* Microsoft C */
- #include <dos.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #endif
-
- #if defined(unix)
- #include <dirent.h>
- #include <pwd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #endif
-
- #if defined(vms)
- #include <rmsdef.h>
- #include <descrip.h>
- #include <stat.h>
- #include <lib$routines.h>
- #endif
-
- #include "dirutils.h"
-
- #if defined(unix)
- static int PatternMatch ();
- static int CheckPattern ();
- static void DerefEnvVar ();
- static char *NextNonENVchar ();
- enum typeENUM {TBD, STR, WILD1, WILDn};
- #endif
-
- /******************************************************************************
- * DirList.
- ******************************************************************************/
-
- int DirList (path, dirS, nameS)
- char *path;
- char ***dirS;
- char ***nameS;
- {
- int i;
- int nFiles = 0;
- int tNameChars = 0;
- int tDirChars = 0;
- char dir[MAX_PATH_LEN + 1];
- char pattern[MAX_NAME_LEN + 1];
-
- struct FILEstruct {
- char *name;
- char *dir;
- struct FILEstruct *next;
- };
-
- struct FILEstruct *FILEhead = NULL;
- struct FILEstruct *FILEtail = NULL;
- struct FILEstruct *FILEptr;
- struct FILEstruct *FILEptrT;
- char *dirP, *nameP;
-
- #if defined(__MSDOS__)
- char pathX[MAX_PATH_LEN + 1];
- struct ffblk ffblk;
- int done;
- #endif
-
- #if defined(MSDOS)
- char pathX[MAX_PATH_LEN + 1];
- struct find_t fileinfo;
- int done;
- #endif
-
- #if defined(unix)
- DIR *dirp;
- struct dirent *dp;
- char dirX[MAX_PATH_LEN + 1];
- #endif
-
- #if defined(vms)
- #if 0
- char curDir[MAX_DIR_LEN + 1];
- #endif
-
- #if 1
- char ignoredDir[MAX_DIR_LEN + 1];
- #endif
-
- char pathX[MAX_PATH_LEN + 1];
- static char pathFound[MAX_PATH_LEN + 1];
- static $DESCRIPTOR (pathDESCR, "");
- static $DESCRIPTOR (pathFoundDESCR, pathFound);
- unsigned long context = 0;
- char name[MAX_NAME_LEN + 1];
- unsigned long int status;
- #endif
-
- /******************************************************************************
- * Find files on MS-DOS machine. Note that only one directory is possible
- * on MS-DOS systems.
- ******************************************************************************/
-
- #if defined(__MSDOS__) | defined(MSDOS)
- ParsePath (path, dir, pattern);
-
- #if 0
- if (dir[0] == NUL) strcpy (dir, "."); /* Default to current directory. */
- #endif
-
- ExpandPath (path, pathX);
-
- #if defined(__MSDOS__)
- done = findfirst (pathX, &ffblk, 0);
- #endif
-
- #if defined(MSDOS)
- done = _dos_findfirst (pathX, 0, &fileinfo);
- #endif
-
- while ( ! done) {
- /****************************************************************************
- * Allocate/setup file structure.
- ****************************************************************************/
-
- FILEptr = (struct FILEstruct *) malloc (sizeof(struct FILEstruct));
-
- #if defined(__MSDOS__)
- FILEptr->name = (char *) malloc (strlen(ffblk.ff_name) + 1);
- strcpy (FILEptr->name, ffblk.ff_name);
- tNameChars += strlen(ffblk.ff_name) + 1;
- #endif
-
- #if defined(MSDOS)
- FILEptr->name = (char *) malloc (strlen(fileinfo.name) + 1);
- strcpy (FILEptr->name, fileinfo.name);
- tNameChars += strlen(fileinfo.name) + 1;
- #endif
-
- nFiles++;
-
- if (FILEhead == NULL) {
- FILEptr->dir = (char *) malloc (strlen(dir) + 1);
- strcpy (FILEptr->dir, dir);
- tDirChars += strlen(dir) + 1;
- }
- else
- FILEptr->dir = NULL;
-
- FILEptr->next = NULL;
-
- /****************************************************************************
- * Add to linkedlist.
- ****************************************************************************/
-
- if (FILEhead == NULL)
- FILEhead = FILEptr;
- else
- FILEtail->next = FILEptr;
-
- FILEtail = FILEptr;
-
- /****************************************************************************
- * Get next matching file.
- ****************************************************************************/
-
- #if defined(__MSDOS__)
- done = findnext (&ffblk);
- #endif
-
- #if defined(MSDOS)
- done = _dos_findnext (&fileinfo);
- #endif
- }
- #endif
-
- /******************************************************************************
- * Find files on UNIX machine. Note that only one directory is possible on
- * UNIX systems.
- ******************************************************************************/
-
- #if defined(unix)
- ParsePath (path, dir, pattern);
-
- #if 0
- if (dir[0] == NUL) strcpy (dir, "."); /* Default to current dir. */
- #endif
-
- if (pattern[0] == NUL) strcpy (pattern, "*"); /* Default to all files. */
-
- ExpandPath (dir, dirX);
-
- #if 1
- if (dirX[0] == NUL) strcpy (dirX, "."); /* Default to current dir. */
- #endif
-
- dirp = opendir (dirX);
- if (dirp == NULL) return -1;
-
- dp = readdir (dirp);
-
- while (dp != NULL) {
- if (PatternMatch (pattern, dp->d_name)) {
- /**************************************************************************
- * Allocate/setup file structure.
- **************************************************************************/
-
- FILEptr = (struct FILEstruct *) malloc (sizeof(struct FILEstruct));
-
- FILEptr->name = (char *) malloc (strlen(dp->d_name) + 1);
- strcpy (FILEptr->name, dp->d_name);
- tNameChars += strlen(dp->d_name) + 1;
- nFiles++;
-
- if (FILEhead == NULL) {
- FILEptr->dir = (char *) malloc (strlen(dir) + 1);
- strcpy (FILEptr->dir, dir);
- tDirChars += strlen(dir) + 1;
- }
- else
- FILEptr->dir = NULL;
-
- FILEptr->next = NULL;
-
- /**************************************************************************
- * Add to linked list.
- **************************************************************************/
-
- if (FILEhead == NULL)
- FILEhead = FILEptr;
- else
- FILEtail->next = FILEptr;
-
- FILEtail = FILEptr;
- }
-
- /****************************************************************************
- * Get next file.
- ****************************************************************************/
-
- dp = readdir (dirp);
- }
-
- closedir (dirp);
- #endif
-
- /******************************************************************************
- * Find files on VMS machine.
- ******************************************************************************/
-
- #if defined(vms)
- ParsePath (path, dir, pattern);
- ExpandPath (path, pathX);
-
- pathDESCR.dsc$a_pointer = pathX;
- pathDESCR.dsc$w_length = strlen(pathX);
-
- while ((status = lib$find_file (&pathDESCR, &pathFoundDESCR, &context,
- NULL, NULL, NULL, NULL)) == RMS$_NORMAL) {
- /****************************************************************************
- * A file was found, NUL terminate and remove trailing blanks.
- ****************************************************************************/
-
- pathFound[pathFoundDESCR.dsc$w_length] = NUL; /* NUL-terminate. */
-
- for (i = strlen(pathFound) - 1;
- i >= 0 && pathFound[i] == ' '; i--) pathFound[i] = NUL;
-
- #if 0 /* SHOULD VERSION BE STRIPPED OFF? */
- if ((cp = strrchr (pathFound, ';')) != NULL) *cp = NUL; /* Strip version. */
- #endif
-
- ParsePath (pathFound, ignoredDir, name);
-
- /****************************************************************************
- * Allocate/setup file structure.
- ****************************************************************************/
-
- FILEptr = (struct FILEstruct *) malloc (sizeof(struct FILEstruct));
-
- FILEptr->name = (char *) malloc (strlen(name) + 1);
- strcpy (FILEptr->name, name);
- tNameChars += strlen(name) + 1;
- nFiles++;
-
- if (FILEhead == NULL) {
- FILEptr->dir = (char *) malloc (strlen(dir) + 1);
- strcpy (FILEptr->dir, dir);
- tDirChars += strlen(dir) + 1;
-
- #if 0
- strcpy (curDir, dir);
- #endif
- }
-
- #if 0
- else
- if (strcmp(dir,curDir) != 0) {
- FILEptr->dir = (char *) malloc (strlen(dir) + 1);
- strcpy (FILEptr->dir, dir);
- tDirChars += strlen(dir) + 1;
- strcpy (curDir, dir);
- }
- #endif
-
- else
- FILEptr->dir = NULL;
-
- FILEptr->next = NULL;
-
- /****************************************************************************
- * Add to linked list.
- ****************************************************************************/
-
- if (FILEhead == NULL)
- FILEhead = FILEptr;
- else
- FILEtail->next = FILEptr;
-
- FILEtail = FILEptr;
- }
-
- status = lib$find_file_end (&context);
- #endif
-
- /******************************************************************************
- * Build directory/file arrays.
- ******************************************************************************/
-
- if (nFiles > 0) {
- /****************************************************************************
- * Setup to traverse linked list.
- ****************************************************************************/
-
- *dirS = (char **) malloc ((nFiles*sizeof(char *)) + tDirChars);
- *nameS = (char **) malloc ((nFiles*sizeof(char *)) + tNameChars);
-
- dirP = (char *) (*dirS) + nFiles*sizeof(char *);
- nameP = (char *) (*nameS) + nFiles*sizeof(char *);
- FILEptr = FILEhead;
-
- /****************************************************************************
- * Traverse linked list of file structures.
- ****************************************************************************/
-
- for (i = 0; i < nFiles; i++) {
- if (FILEptr->dir != NULL) {
- strcpy (dirP, FILEptr->dir);
- (*dirS)[i] = dirP;
- dirP += strlen(FILEptr->dir) + 1;
- }
- else
- (*dirS)[i] = (*dirS)[i-1]; /* Same as the last one. A directory
- must exist for the first file. */
- strcpy (nameP, FILEptr->name);
- (*nameS)[i] = nameP;
- nameP += strlen(FILEptr->name) + 1;
-
- FILEptr = FILEptr->next;
- }
-
- /****************************************************************************
- * Free linked list of file structures.
- ****************************************************************************/
-
- FILEptr = FILEhead;
-
- while (FILEptr != NULL) {
- FILEptrT = FILEptr;
- FILEptr = FILEptr->next;
- if (FILEptrT->dir != NULL) free (FILEptrT->dir);
- free (FILEptrT->name);
- free (FILEptrT);
- }
- }
- else {
- /****************************************************************************
- * No files found.
- ****************************************************************************/
-
- *nameS = NULL;
- *dirS = NULL;
- }
-
- return nFiles; /* Return number of files found. */
- }
-
- /******************************************************************************
- * ParsePath.
- ******************************************************************************/
-
- void ParsePath (path, dir, pattern)
- char *path;
- char *dir;
- char *pattern;
- {
- char *cp;
- int len;
-
- #if defined(unix)
- if (IsDir(path)) {
- strcpy (dir, path);
- pattern[0] = NUL;
- }
- else {
- cp = strrchr (path, '/');
- if (cp == NULL) {
- dir[0] = NUL;
- strcpy (pattern, path);
- }
- else {
- len = cp - path; /* '/' not returned as part of directory. */
- strncpy (dir, path, len);
- dir[len] = NUL;
- strcpy (pattern, cp + 1);
- }
- }
- #endif
-
- #if defined(__MSDOS__) | defined(MSDOS)
- if (IsDir(path)) {
- strcpy (dir, path);
- pattern[0] = NUL;
- }
- else {
- char *cp1 = strrchr (path, ':');
- char *cp2 = strrchr (path, '\\');
-
- cp = (cp1 > cp2 ? cp1 : cp2);
-
- if (cp == NULL) {
- dir[0] = NUL;
- strcpy (pattern, path);
- }
- else {
- if (cp1 == NULL) {
- len = cp2 - path; /* '\' not returned as part of directory. */
- strncpy (dir, path, len);
- dir[len] = NUL;
- }
- else {
- if (cp2 == NULL) {
- len = cp1 - path + 1; /* ':' is returned as part of directory. */
- strncpy (dir, path, len);
- dir[len] = NUL;
- }
- else {
- if (cp1 + 1 == cp2)
- len = cp2 - path + 1; /* ':' is returned as part of directory. */
- else
- len = cp2 - path; /* ':' not returned as part of directory. */
- strncpy (dir, path, len);
- dir[len] = NUL;
- }
- }
- strcpy (pattern, cp + 1);
- }
- }
- #endif
-
- #if defined(vms)
- char *cp1 = strrchr (path, ':');
- char *cp2 = strrchr (path, ']');
-
- cp = (cp1 > cp2 ? cp1 : cp2);
-
- if (cp == NULL) {
- dir[0] = NUL;
- strcpy (pattern, path);
- }
- else {
- len = cp - path + 1; /* ':' or ']' returned as part of directory. */
- strncpy (dir, path, len);
- dir[len] = NUL;
- strcpy (pattern, cp + 1);
- }
- #endif
-
- return;
- }
-
- /******************************************************************************
- * ExpandPath.
- ******************************************************************************/
-
- void ExpandPath (shortP, longP)
- char *shortP;
- char *longP;
- {
- #if defined(unix)
- int len;
- char username[MAX_USERNAME_LEN+1];
- char tempP[MAX_PATH_LEN+1];
- char *tail;
- struct passwd *pw;
- #endif
-
- #if defined(unix)
- DerefEnvVar (shortP, tempP);
-
- if (tempP[0] != '~')
- strcpy (longP, tempP);
- else {
- tail = strchr (tempP, '/');
-
- if (tail != NULL) {
- len = tail - (tempP + 1);
-
- if (len > 0) {
- strncpy (username, tempP + 1, len);
- username[len] = NUL;
- pw = getpwnam (username);
- }
- else
- pw = getpwuid (getuid());
-
- if (pw != NULL)
- strcpy (longP, pw->pw_dir);
- else
- strcpy (longP, "?");
-
- strcat (longP, tail);
- }
- else {
- if (tempP[1] != NUL)
- pw = getpwnam (tempP + 1);
- else
- pw = getpwuid (getuid());
-
- if (pw != NULL)
- strcpy (longP, pw->pw_dir);
- else
- strcpy (longP, "?");
- }
- }
- #endif
-
- #if defined(__MSDOS__) | defined(MSDOS)
- strcpy (longP, shortP);
- #endif
-
- #if defined(vms)
- strcpy (longP, shortP);
- #endif
-
- return;
- }
-
- /******************************************************************************
- * IsDir (directory).
- ******************************************************************************/
-
- int IsDir (path)
- char *path;
- {
- char pathX[MAX_PATH_LEN+1];
- struct stat st;
-
- ExpandPath (path, pathX);
-
- #if defined(unix) | defined(__MSDOS__) | defined(MSDOS)
- if (stat(pathX, &st) == 0)
- return ((st.st_mode & S_IFDIR) ? TRUE : FALSE);
- else
- return FALSE;
- #endif
-
- #if defined(vms)
- if (IsReg(pathX)) /* First check for possible logical name
- defined to be a full file specification
- (not just a directory). */
- return FALSE;
- else { /* If not, check if the path ends with a ':'
- (logical name) or ']' (directory). */
- int x = strlen(pathX) - 1;
- if (pathX[x] == ':' || pathX[x] == ']')
- return TRUE;
- else
- return FALSE;
- }
- #endif
-
- }
-
- /******************************************************************************
- * IsReg (regular file). 'stat' on VMS and MS-DOS systems will indicate a
- * regular file if ANY file can be found matching a
- * wildcard spec. On UNIX systems, that doesn't happen.
- ******************************************************************************/
-
- int IsReg (path)
- char *path;
- {
- char pathX[MAX_PATH_LEN+1];
- struct stat st;
-
- ExpandPath (path, pathX);
-
- #if defined(vms)
- if (strchr(pathX,'*') != NULL || strchr(pathX,'%') != NULL) return FALSE;
- #endif
-
- #if defined(__MSDOS__) | defined(MSDOS)
- if (strchr(pathX,'*') != NULL || strchr(pathX,'?') != NULL) return FALSE;
- #endif
-
- if (stat(pathX, &st) == 0)
- return ((st.st_mode & S_IFREG) ? TRUE : FALSE);
- else
- return FALSE;
- }
-
- /******************************************************************************
- * PatternMatch. (Only used on UNIX systems).
- ******************************************************************************/
-
- #if defined(unix)
- static int PatternMatch (pattern, name)
- char *pattern;
- char *name;
- {
- enum typeENUM types[MAX_PATTERNS];
- char *strings[MAX_PATTERNS];
- int nTypes = 0;
- int len, i, result;
-
- for (i = 0; i < MAX_PATTERNS; i++) types[i] = TBD;
-
- for (i = 0; pattern[i] != NUL; i++)
- switch (pattern[i]) {
- case '?':
- types[nTypes++] = WILD1;
- break;
- case '*':
- if (nTypes == 0 || types[nTypes] != WILDn) types[nTypes++] = WILDn;
- break;
- default:
- if (types[nTypes] == TBD) {
- types[nTypes] = STR;
- strings[nTypes] = (char *) malloc (MAX_NAME_LEN + 1);
- strings[nTypes][0] = pattern[i];
- strings[nTypes][1] = NUL;
- nTypes++;
- }
- else {
- len = strlen (strings[nTypes-1]);
- strings[nTypes-1][len] = pattern[i];
- strings[nTypes-1][len+1] = NUL;
- }
- }
-
- result = CheckPattern (nTypes, types, strings, name);
-
- for (i = 0; i < MAX_PATTERNS; i++) {
- if (types[i] == STR) free (strings[i]);
- }
-
- return result;
- }
- #endif
-
- /******************************************************************************
- * CheckPattern. (Only used on UNIX systems).
- ******************************************************************************/
-
- #if defined(unix)
- static int CheckPattern (nTypes, types, strings, name)
- int nTypes;
- enum typeENUM types[];
- char *strings[];
- char *name;
- {
- int sp = 0;
- int i, j;
-
- for (i = 0; i < nTypes; i++)
- switch (types[i]) {
- case STR:
- if (strncmp(&name[sp],strings[i],strlen(strings[i])) != 0)
- return FALSE;
- else
- sp += strlen(strings[i]);
- break;
- case WILD1:
- if (name[sp] == NUL)
- return FALSE;
- else
- sp++;
- break;
- case WILDn:
- if (i == nTypes-1) /* At last type to check? */
- return TRUE;
- else {
- for (j = i; name[j] != NUL; j++)
- if (CheckPattern (nTypes-i-1, &types[i+1],
- &strings[i+1], &name[j])) return TRUE;
- return FALSE;
- }
- }
-
- if (name[sp] == NUL)
- return TRUE;
- else
- return FALSE;
- }
- #endif
-
- /******************************************************************************
- * DerefEnvVar. (Only used on UNIX systems).
- ******************************************************************************/
-
- #if defined(unix)
- static void DerefEnvVar (shortP, longP)
- char *shortP; /* Short path (with environment
- variables). */
- char *longP; /* Long path (with environment
- variables dereferenced). */
- {
- char *Sptr = shortP; /* Current position in "short" path. */
- char *Lptr = longP; /* End position in "long" path. */
- char *DOLLARptr; /* Pointer to '$' in "short" path. */
- char *ENVptr; /* Pointer to environment variable in "short" path. */
- char *DEREFptr; /* Pointer to dereferenced environment variable
- "value". */
- size_t len;
- char *ptr;
- char ENVvar[MAX_ENVVAR_LEN + 1]; /* Environment variable. */
-
- *Lptr = NUL;
-
- for (;;) {
- DOLLARptr = strchr (Sptr, '$');
- if (DOLLARptr != NULL) {
- len = DOLLARptr - Sptr;
- if (len > 0) {
- strncpy (Lptr, Sptr, len);
- Lptr += len;
- *Lptr = NUL;
- }
-
- if (*(DOLLARptr + 1) == '{') {
- ENVptr = DOLLARptr + 2;
- ptr = strchr (ENVptr, '}');
- if (ptr != NULL) {
- len = ptr - ENVptr;
- Sptr = ptr + 1;
- }
- else {
- len = strlen (ENVptr);
- Sptr = ENVptr + len;
- }
- }
- else {
- ENVptr = DOLLARptr + 1;
- ptr = NextNonENVchar (ENVptr + 1);
- if (ptr != NULL) {
- len = ptr - ENVptr;
- Sptr = ptr;
- }
- else {
- len = strlen (ENVptr);
- Sptr = ENVptr + len;
- }
- }
-
- strncpy (ENVvar, ENVptr, len);
- ENVvar[len] = NUL;
-
- DEREFptr = getenv (ENVvar);
-
- len = strlen (DEREFptr);
- if (len > 0) {
- strncpy (Lptr, DEREFptr, len);
- Lptr += len;
- *Lptr = NUL;
- }
- }
- else {
- strcat (Lptr, Sptr);
- return;
- }
- }
- }
- #endif
-
- /******************************************************************************
- * NextNonENVchar. (Only used on UNIX systems).
- ******************************************************************************/
-
- #if defined(unix)
- static char *NextNonENVchar (ptr)
- char *ptr;
- {
- while (*ptr != NUL) {
- if ('\0' <= *ptr && *ptr <= '/') return ptr;
- if (':' <= *ptr && *ptr <= '@') return ptr;
- if ('[' <= *ptr && *ptr <= '^') return ptr;
- if (*ptr == '`') return ptr;
- if ('{' <= *ptr && *ptr <= '\377') return ptr;
- ptr++;
- }
- return NULL;
- }
- #endif
-
- /******************************************************************************
- * AppendToDir. If necessary, appends a '/' (UNIX) or a '\' (MS DOS) to make
- * a directory specification to which the file name can then be
- * appended.
- ******************************************************************************/
-
- void AppendToDir (dir, name)
- char *dir;
- char *name;
- {
- #if defined(vms)
- strcat (dir, name);
- #endif
-
- #if defined(unix)
- if (dir[0] != NUL) {
- if (dir[strlen(dir) - 1] != '/') strcat (dir, "/");
- }
- strcat (dir, name);
- #endif
-
- #if defined(__MSDOS__) | defined(MSDOS)
- if (dir[0] != NUL) {
- if (dir[strlen(dir) - 1] != '\\') strcat (dir, "\\");
- }
- strcat (dir, name);
- #endif
-
- return;
- }
-
- /******************************************************************************
- * RemoveExtensions. Locates the last '.' in a file name and replaces it with
- * a NUL. This effectively removes the file extension. If
- * the file name does not have an extension, this could have
- * undesired effects.
- ******************************************************************************/
-
- void RemoveExtensions (nFiles, files)
- int nFiles;
- char *files[];
- {
- int i;
- char *ptr;
-
- for (i = 0; i < nFiles; i++)
- if ((ptr = strrchr(files[i],'.')) != NULL) *ptr = NUL;
-
- return;
- }
-